package ar.edu.unlu.sistemas.ws.business;

import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

public class CORI {
	
	private String currentPeerId;
	private String currentTerm;
	private Integer df;
	private Integer cw;
	private Integer cf;
	private Double avg_cw;
	private Integer c;
	private Map<String,Integer> cf_byTerm = new HashMap<String,Integer>();
	private static final Float b = new Float(0.4);

	private static Logger logger = Logger.getLogger("cori");
	
	private Double calculateT(){
		df = IndexManager.getInstance().getDocumentFrecuency(currentPeerId,currentTerm);
		return df/(df+50+((150*cw)/avg_cw));
	}
	
	private Double calculateI(){
		cf = cf_byTerm.get(currentTerm);
		return Math.log((c+0.5)/cf)/Math.log(c+1.0);
	}
	
	private Double calculateP(String qTerm){
		currentTerm = qTerm;
		return b+((1-b)*calculateT()*calculateI());
	}
	
	private Double calculateCori(List<String>  query, String peerId) {
		currentPeerId = peerId;
		cw = IndexManager.getInstance().getNumberOfTerms(currentPeerId);
		Double ac = new Double(0);
		for (String qTerm : query) ac+=calculateP(qTerm);
		return ac/query.size();
	}
	
	public List<ResourceRank> rankResources(String query) {
		Set<String> peersIds = PeerManager.getInstance().getPeers();
		List<String> queryList = QueryHelper.indexQuery(query);
		Double ac = new Double(0);
		c = peersIds.size();
		for (String peerId : peersIds) ac += IndexManager.getInstance().getNumberOfTerms(peerId);
		avg_cw = ac/ c;
		for (String queryTerm : queryList) cf_byTerm.put(queryTerm, IndexManager.getInstance().getNumberOfResourcesWithTerm(queryTerm));
		List<ResourceRank>  result = new LinkedList<ResourceRank> ();
		for (String peerId : peersIds)result.add(new ResourceRank(peerId,calculateCori(queryList, peerId)));
		Collections.sort(result);
		logger.info("Resultados arrojados por CORI (peerId:rating) para query \""+query+"\" "+result);
		return result;
	}
	
	
	
	public static class ResourceRank implements Comparable<ResourceRank> {
		public ResourceRank (String peerId,Double rank) {
			this.peerId = peerId;
			this.rank = rank;
		}
		String peerId;
		Double rank;
		public int compareTo(ResourceRank o) {
			return o.rank.compareTo(this.rank);
		}
		public String toString(){
			return "[peerId:"+peerId+"-rank:"+rank+"]";
		}
	}

}
